/********************************************************************
	Crytek Source File.
  Copyright (C), Crytek Studios, 2001-2009.
 -------------------------------------------------------------------------
  File name:   MNMPathfinder.h
	$Id$
  Description: 
  
 -------------------------------------------------------------------------
  History:
  - 06.05.2011 : Created by Francesco Roccucci

*********************************************************************/

#ifndef _MNMPATHFINDER_H_
#define _MNMPATHFINDER_H_

#include "Navigation/MNM/MNM.h"
#include "NavPath.h"
#include <AgePriorityQueue.h>
#include <INavigationSystem.h>
#include <IPathfinder.h>

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

class CMNMPathfinder : public IMNMPathfinder
{
	struct QueuedRequest
	{
		QueuedRequest()
			: pRequester(NULL)
			, agentTypeID(0)
		{

		}

		QueuedRequest(IAIPathAgent* _pRequester, NavigationAgentTypeID _agentTypeID, const MNMPathRequest& _request)
			: pRequester(_pRequester)
			, agentTypeID(_agentTypeID)
			, requestParams(_request)
		{

		}

		IAIPathAgent*         pRequester;
		NavigationAgentTypeID agentTypeID;	
		MNMPathRequest        requestParams;
	};
	typedef AgePriorityQueue<QueuedRequest>	RequestQueue;

	struct ProcessingRequest
	{
		ProcessingRequest()
			: pRequester(NULL)
			, meshID(0)
			, fromTriangleID(0)
			, toTriangleID(0)
			, queuedID(0)
		{

		}

		ILINE void Reset() { (*this) =  ProcessingRequest(); }
		ILINE bool IsValid() const { return (queuedID != 0); };

		IAIPathAgent*       pRequester;
		NavigationMeshID    meshID;
		MNM::TriangleID		fromTriangleID;
		MNM::TriangleID		toTriangleID;
	
		MNMPathRequest		requestParams;
		MNMQueuedPathID		queuedID;
	};

public:

	CMNMPathfinder();
	~CMNMPathfinder();

	void Reset();

	MNMQueuedPathID RequestPathTo(IAIPathAgent* pRequester, const MNMPathRequest& request);
	void CancelPathRequest(MNMQueuedPathID requestId);

	const INavPath &GetNavPath() const { return m_navPath; }
	const CNavPath &GetCNavPath() const { return m_navPath; }

	void Update();

	void OnNavigationMeshChanged(NavigationMeshID meshId, MNM::TileID tileId);

private:

	MNMQueuedPathID QueuePathRequest(IAIPathAgent *pRequester, const MNMPathRequest& request);
	
	bool SetupForNextPathRequest(MNMQueuedPathID requestID, const QueuedRequest& request);
	bool ProcessPathRequest();
	void PathRequestFailed(MNMQueuedPathID requestID, const QueuedRequest& request);

	inline Vec3 TriangleCenter(const Vec3& a, const Vec3& b, const Vec3& c) 
	{ 
		return (a + b + c) / 3.f; 
	}

	void DebugStatistics();

	CNavPath m_navPath;

	RequestQueue	  m_requestedPathsQueue;
	QueuedRequest     m_processingRequestData;
	ProcessingRequest m_processingRequest;

	MNM::AStarOpenList	m_AStarOpenList;
};

#endif // _MNMPATHFINDER_H_